﻿(function ($) {
    Array.prototype.where = function (dx, propName) {
        var i = 0;
        var tmp = undefined;
        var flag = false;
        if (propName == undefined)
            propName = "ID";
        $.each(this, function (i, val) {
            for (var i in this) {
                if (i == propName && this[i] == dx) {
                    tmp = this;
                    return false;
                }
            }
        });
        return tmp;
    }
    var validateform = function ($this, parm) {
        this.validateControls = [],
            this.$this = $this,
            this.fields = parm.fields;
        this.parm = parm;

    }
    validateform.prototype = {

        reset: function () {
            var me = this;
            $.each(me.validateControls, function (i, validate) {
                //validate.parent.removeClass('has-error');
                validate.parent.removeClass('has-success');
                if (validate.notEmpty) {
                    if (validate.notEmpty.html)
                        validate.notEmpty.html.removeClass('no-validate');
                    if (validate.label) {
                        var b = validate.label.find('b');
                        if (b.length > 0) {
                            b.remove();
                        }
                        var data = validate.control.attr("data-no-validate");
                        if (data && data == 'true') {
                            validate.label.html(validate.label.html().replace("<b style='color:#F00;'>* </b>", ''));
                        }
                        else {


                            validate.label.html("<b style='color:#F00;'>* </b>" + validate.label.html());
                        }
                    }
                }
                if (validate.dataType && validate.dataType.html)
                    validate.dataType.html.removeClass('no-validate');
                if (validate.callback) {
                    if (validate.callback instanceof Array) {
                        $.each(validate.callback, function (i, val) {
                            val.html.removeClass('no-validate');
                        })
                    }
                    else
                        validate.callback.html.removeClass('no-validate');
                }
                validate.remove.attr('class', 'form-control-feedback glyphicon glyphicon-ok');
                validate.remove.css('display', 'none');

                if (validate.control[0].tagName.toLowerCase() == 'select') {
                    validate.control.attr('style', '');
                    //padding-right: 40px;
                }


            })

        },

        ResetSubmitBtn: function (submitBtn) {
            var me = this;
            if (submitBtn) {

                submitBtn.on("click", function () {
                    var that = $(this);
                    if (!that.hasClass('disabled')) {
                        try {
                            var flag = true;
                            $.each(me.validateControls, function (i, val) {
                                var tmp = me.validateControl(val);
                                flag = flag && tmp;
                            })
                            if (flag && me.parm.submitHandler) {
                                //$(this).button('loading');
                                var form = me.$this.is('form') ? me.$this : me.$this.find('form');
                                var obj = {};
                                if (form.length == 1)
                                    obj = me.collectdata(form);
                                else {
                                    form.each(function (i) {
                                        var $form = $(this);
                                        var name = $form.attr('name') || "form" + i;
                                        obj[name] = me.collectdata($form);
                                    });
                                }
                                me.parm.submitHandler(obj, me.$this, that);
                            }
                            else {
                                if (me.parm.unvalidate) {
                                    me.parm.unvalidate();
                                }
                            }
                        } catch (e) {
                            alert(e);
                            $(this).button('reset');
                        }
                        return false;
                    }
                })
            }

        },

        Length: function (str, length) {
            var total = 0, charCode, i, len;
            //for (i = 0, len = str.length; i < len; i++) {
            //    charCode = str.charCodeAt(i);
            //    if (charCode <= 0x007f) {
            //        total += 1;
            //    } else if (charCode <= 0x07ff) {
            //        total += 2;
            //    } else if (charCode <= 0xffff) {
            //        total += 3;
            //    } else {
            //        total += 4;
            //    }
            //}
            if (str == undefined || str == null)
                return true;
            return str.length <= length;
        },

        isnull: function (v) {
            return (v == undefined || v == null || v == '');
        },
        email: function (str) {
            if (str.length == 0)
                return true;

            var myRegExp = /[a-z0-9-.]{1,30}@[a-z0-9-]{1,65}.(com|net|org|info|biz|([a-z]{2,3}.[a-z]{2}))/;
            return myRegExp.test(str)
        },

        int: function (str) {
            if (str.length == 0)
                return true;
            var pattern = /^[1-9]\d*|0$/; //匹配非负整数
            str = str.replace(/[^\d]/g, "");
            return pattern.test(str);
        },

        decimal: function (str) {
            var me = this;
            if (me.int(str)) return true;

            var re = /^[-]{0,1}(\d+)[\.]+(\d+)$/;
            if (re.test(str)) {
                if (RegExp.$1 == 0 && RegExp.$2 == 0) return false;
                return true;
            }
            return false;
        },
        //YYYY-MM-DD
        IsDate: function (str) {
            var me = this;
            if (me.isnull(str)) return true;
            var reg = /^(\d{1,4})(-|\/)(\d{1,2})\2(\d{1,2})$/;
            return reg.test(str);

        },

        //YYYY-MM-DD hh:mm:ss
        IsDateTime: function (str) {
            var me = this;
            if (me.isnull(str)) return true;
            var reg = /^(\d{1,4})(-|\/)(\d{1,2})\2(\d{1,2}) (\d{1,2}):(\d{1,2}):(\d{1,2})$/;
            return reg.test(str);
        },

        IsDateWithMinitue: function (str) {
            var me = this;
            if (me.isnull(str)) return true;
            var reg = /^(\d{1,4})(-|\/)(\d{1,2})\2(\d{1,2}) (\d{1,2}):(\d{1,2})$/;
            return reg.test(str);
        },

        //判断日期类型是否为hh:mm:ss格式的类型
        IsTime: function (str) {
            var me = this;
            if (me.isnull(str)) return true;
            reg = /^((20|21|22|23|[0-1]\d)\:[0-5][0-9])(\:[0-5][0-9])?$/
            return reg.test(str);

        },

        validateControl: function (validate, isCircle) {
            var me = this;
            var flag = true;
            var data = validate.control.attr("data-no-validate");
            if (data && data == 'true')
                return true;


            var $value = validate.control.val();
            if (validate.notEmpty && validate.notEmpty.html) {
                validate.notEmpty.html.removeClass('no-validate');
                //validate.label = me.getlabel(validate.control);


            }
            if (validate.dataType && validate.dataType.html)
                validate.dataType.html.removeClass('no-validate');
            if (validate.callback) {
                if (validate.callback instanceof Array) {
                    $.each(validate.callback, function (i, val) {
                        val.html.removeClass('no-validate');
                    })
                }
                else
                    validate.callback.html.removeClass('no-validate');
            }

            if (validate.notEmpty) {
                flag = flag && !me.isnull($value);
                if (!flag && validate.notEmpty.html) {
                    validate.notEmpty.html.addClass('no-validate');
                }
            }


            if (flag && validate.dataType) {
                switch (validate.dataType.dataType.dataType) {
                    case 'decimal':
                        flag = flag && me.decimal($value);
                        break;
                    case 'int':
                        flag = flag && me.int($value);
                        break;
                    case 'email':
                        flag = flag && me.email($value);
                        break;
                    case 'datetime':
                        var format = validate.dataType.dataType.format ? validate.dataType.dataType.format : "YYYY-MM-DD";
                        if (format == "YYYY-MM-DD hh:mm:ss")
                            flag = flag && me.IsDateTime($value);
                        else if (format == "hh:mm:ss")
                            flag = flag && me.IsTime($value);
                        else if (format == "YYYY-MM-DD hh:mm")
                            flag = flag && me.IsDateWithMinitue($value);
                        else flag = flag && me.IsDate($value);
                        break;
                }

                if (!flag && validate.dataType && validate.dataType.html) {
                    validate.dataType.html.addClass('no-validate');
                }
            }
            function validateCall(callback, $value) {
                var flag = callback.callback($value);
                if (typeof (callback.message) == "function")
                    callback.html.html(callback.message($value))
                flag ? callback.html.removeClass('no-validate') : callback.html.addClass('no-validate');
                return flag;
            }


            if (flag && validate.callback) {
                if (validate.callback instanceof Array) {
                    $.each(validate.callback, function (i, val) {
                        flag = flag && validateCall(val, $value);
                        if (!flag) {
                            return false;
                        }
                    })
                }
                else {
                    flag = flag && validateCall(validate.callback, $value);
                    //flag ? validate.callback.html.removeClass('no-validate') : validate.callback.html.addClass('no-validate');
                }
            }
            if (flag && validate.Length) {
                flag = flag && me.Length($value, validate.Length.Length);
                flag ? validate.Length.html.removeClass('no-validate') : validate.Length.html.addClass('no-validate');
            }

            if (validate.reference) {
                if (!isCircle) {
                    var field = validate.reference;
                    $.each(me.validateControls, function (i, val) {
                        if (field == val.name) {
                            me.validateControl(val, true);
                        }
                    })
                }
            }
            if (validate.control[0].tagName.toLowerCase() == 'select') {
                validate.control.attr('style', 'padding-right: 36px !important');
                //
            }
            flag ?
                (validate.parent.removeClass('has-error'),
                    validate.parent.addClass('has-success'),
                    validate.remove.attr('class', 'form-control-feedback glyphicon glyphicon-ok'),
                    validate.remove.css('display', 'block')) :
                (validate.parent.addClass('has-error'),
                    validate.parent.removeClass('has-success'),
                    validate.remove.attr('class', 'form-control-feedback glyphicon glyphicon-remove'),
                    validate.remove.css('display', 'block'));
            return flag;
        },

        validatefalse: function ($val, message) {
            if ($val.errordiv) $val.errordiv.html(message);
            else
                $val.errordiv = $("<div>").html(message);
            $val.after($val.errordiv);
            return false;
        },

        getlabel: function (control, name, time) {
            var me = this;
            var label = $("label", control.parent());
            if (label.length == 0 || time > 3)
                return me.getlabel(control.parent(), name, ++time);
            var tmp = $("label[for=" + name + "]", control.parent());
            if (tmp.length > 0)
                return tmp;

            return $(label[0]);
        },

        init: function (name) {
            var me = this;
            var validate = {};
            //待验证控件

            validate.control = $($.format("*[name={0}]", name), me.$this);


            if (validate.control.length == 0)
                throw ({message: "未找到控件" + validate.control.selector});

            validate.parent = validate.control.parent();
            validate.name = name;
            if (validate.control.length > 0) {
                me.validateControls.push(validate);
                validate.control.parent().addClass('has-feedback');//.addClass('has-error');
                validate.remove = $("<i style='display:none;' class='form-control-feedback glyphicon glyphicon-remove' data-bv-icon-for='EMPLOYEE_NAME'></i>");
                validate.control.after(validate.remove);

                validate.label = me.getlabel(validate.control, name);
                if (me.fields[name].validators.notEmpty) {
                    validate.notEmpty = {};


                    if (me.fields[name].validators.notEmpty.message) {
                        validate.notEmpty.html = $("<div class='help-block'>").html(me.fields[name].validators.notEmpty.message);
                        validate.control.after(validate.notEmpty.html);
                    }

                    var data = validate.control.attr("data-no-validate");
                    if (data && data == 'true') {
                        validate.label.html(validate.label.html().replace("<b style='color:#F00;'>* </b>", ''));
                    }
                    else {
                        validate.label.html("<b style='color:#F00;'>* </b>" + validate.label.html());
                    }
                }
                if (me.fields[name].validators.dataType) {
                    validate.dataType = {};
                    validate.dataType.dataType = me.fields[name].validators.dataType;
                    validate.dataType.html = $("<div  class='help-block'>").html(me.fields[name].validators.dataType.message);
                    if (me.fields[name].validators.dataType.message)
                        validate.control.after(validate.dataType.html);
                }
                if (me.fields[name].validators.callback) {
                    validate.callback = [];
                    if (me.fields[name].validators.callback instanceof Array) {
                        $.each(me.fields[name].validators.callback, function (i, val) {
                            var callback = {};
                            callback.html = $("<div  class='help-block'>")
                            if (typeof (val.message) == "function") {
                                callback.message = val.message;
                            } else {
                                callback.html.html(val.message)
                                //validate.callback.html(me.fields[name].validators.callback.qumei);
                            }

                            validate.control.after(callback.html);
                            callback.callback = val.callback;
                            validate.callback.push(callback);
                        })

                    }
                    else {
                        validate.callback = {};
                        validate.callback.html = $("<div  class='help-block'>");
                        if (typeof (me.fields[name].validators.callback.message) == "function") {
                            validate.callback.message = me.fields[name].validators.callback.message;
                        } else {
                            validate.callback.html.html(me.fields[name].validators.callback.message);
                        }


                        validate.control.after(validate.callback.html);
                        validate.callback.callback = me.fields[name].validators.callback.callback;
                    }
                }
                if (me.fields[name].validators.Length) {
                    validate.Length = {};
                    validate.Length.Length = me.fields[name].validators.Length;
                    validate.Length.html = $("<div  class='help-block'>").html('输入过长，最大长度：' + me.fields[name].validators.Length);
                    validate.control.after(validate.Length.html);
                }

                if (me.fields[name].reference) {
                    validate.reference = me.fields[name].reference;
                }

                var tagName = validate.control[0].tagName.toLowerCase();
                if (tagName == "input" || tagName == "textarea") {
                    //validate.control.on('input propertychange blur', function () {
                    //    validateControl(validate);
                    //})

                    validate.control.on({
                        'input': function () {
                            me.validateControl(validate);
                        }, 'validate': function () {
                            me.validateControl(validate);
                        }, 'blur': function () {
                            me.validateControl(validate);
                        }
                    })
                } else if (tagName == "select") {
                    validate.control.on({
                        'change': function () {
                            me.validateControl(validate);
                        }, 'validate': function () {
                            me.validateControl(validate);
                        }
                    });
                }

            }


        },

        collectdata: function (form) {
            var me = this;
            var obj = form.serializeArray();
            var obj_data = {};
            $.each(obj, function (i, val) {
                if (!obj_data[val.name])
                    obj_data[val.name] = val.value;
                else {
                    obj_data[val.name] += "," + val.value;
                }
                var myvalidate = me.validateControls.where(val.name, 'name');

                if (myvalidate && myvalidate.dataType && myvalidate.dataType.dataType && myvalidate.dataType.dataType.dataType == 'datetime') {
                    if (!me.isnull(obj_data[val.name])) {
                        if (obj_data[val.name].length == 10)
                            obj_data[val.name] = obj_data[val.name] + "T00:00:00Z";
                        else if (obj_data[val.name].length == 16) {
                            var date = obj_data[val.name].split(' ');
                            obj_data[val.name] = date[0] + "T" + date[1] + ":00Z";
                        }
                        else if (obj_data[val.name].length > 16) {
                            var date = obj_data[val.name].split(' ');
                            obj_data[val.name] = date[0] + "T" + date[1] + "Z";
                        }
                    }

                }
            })

            var $radio = $('input[type=radio],input[type=checkbox]', form);
            if ($radio.length > 0) {
                $radio.each(function(){
                    if(!obj_data.hasOwnProperty(this.name)){
                        obj_data[this.name] = '';
                    }
                })
            }


            return obj_data;
        }
    }

    $.fn.validate = function (parm) {
        var $this = $(this);
        var validate_i = new validateform($this, parm);
        parm.Validate = validate_i;

        var fields = parm.fields;
        if (fields) {
            for (i in fields) {
                validate_i.init(i);
            }
        }


        if (parm.submitBtn) {
            if (!(parm.submitBtn instanceof jQuery))
                parm.submitBtn = $("#" + parm.submitBtn);
        }

        var submitBtn = parm.submitBtn || $this.find("[type = 'submit']");
        validate_i.ResetSubmitBtn(submitBtn);


        var form = $this.is('form') ? $this : $this.find('form');
        form.each(function (i) {
            var $form = $(this);
            var resetBtn = $form.find("input[type = 'reset']");
            if (!resetBtn || resetBtn.length == 0) {
                resetBtn = $("<input style='display:none' type='reset'>");
                $form.append(resetBtn);

                resetBtn.on('reset', function () {
                    resetBtn.click();
                    validate_i.reset();
                    submitBtn.button('reset');
                    return false;

                });
            }
        });


        var resetBtn = $this.find("input[type = 'reset']");
        if (!parm.resetBtn || resetBtn.length == 0)
            parm.resetBtn = resetBtn;
        else
            parm.resetBtn.click(function () {
                resetBtn.trigger("reset");
            });
        form.on("reset", function () {
            resetBtn.click();
        });
        $this.on("reset", function () {
            resetBtn.click();
        });
    }
})(jQuery);

